'use strict';

var fs = require('fs');

//require our websocket library 
var WebSocketServer = require('ws').Server; 

var cfg = {
    ssl: false,
    port: 3000,
    ssl_key: '/home/luyao/ssl/domain.key',
    ssl_cert: '/home/luyao/ssl/chained.pem'
  };

var httpServ = (cfg.ssl) ? require('https') : require('http');

var app = null;

// dummy request processing
var processRequest = function (req, res) {
    res.writeHead(200);
    res.end('All glory to WebSockets!\n');
  };

if (cfg.ssl) {
    app = httpServ.createServer({
        // providing server with  SSL key/cert
        key: fs.readFileSync(cfg.ssl_key),
        cert: fs.readFileSync(cfg.ssl_cert)

    }, processRequest).listen(cfg.port);
} else {
    app = httpServ.createServer(processRequest).listen(cfg.port);
}

var websocket_server = new WebSocketServer({server: app, perMessageDeflate: false,}); 

//all connected to the server users 
var users = {};

//TODO: maintain the last active time of connection
//
/* when a user connects to our sever, NOTE: all request get 200 response */
websocket_server.on('connection', function(connection) {
    console.log("User connected");
    //when server gets a message from a connected user 
    connection.on('message', function(message) {
        console.log("got message: ", message, "\n");
        var data; 
        try {
            data = JSON.parse(message); 
        } catch (e) {
            console.log("Invalid JSON"); 
            data = {}; 
        }
        
        switch (data.type) {
            case "ping-signal": 
                sendTo(connection, {type: "pong-signal", from: ""}); 
                break;

            case "login": 
                console.log("User logged", data.name); 
                //if anyone is logged in with this username then refuse 
                if(users[data.name]) { 
                    sendTo(connection, {type: "login", success: false}); 
                } else { 
                    //save user connection on the server 
                    users[data.name] = connection; 
                    connection.name = data.name; 
                    sendTo(connection, {type: "login", success: true}); 
                }
                break;

            case "message":
                var conn = users[data.name];
                if(conn != null) {
                    // setting that UserA connected with UserB 
                    sendTo(conn, {type: "message", payload: data.payload, from: connection.name}); 
                }
                break;
                
            case "file-transform": 
                // for ex. UserA wants get a file from UserB
                console.log("Sending file-transform to: ", data.name);
                var conn = users[data.name]; 
                if(conn != null) {
                    sendTo(conn, {type: "file-transform", payload: data.payload, from: connection.name}); 
                }
                break;
    
            case "file-transform-parameter": 
                // file parameter: filePath, fileSize
                console.log("Sending file-transform-parameter to: ", data.name);
                var conn = users[data.name]; 
                if(conn != null) {
                    sendTo(conn, {type: "file-transform-parameter", payload: data.payload, from: connection.name}); 
                }
                break;
    
            case "file-transform-parameter-accept":
                var conn = users[data.name];
                if(conn != null) {
                    // setting that UserA connected with UserB 
                    sendTo(conn, {type: "file-transform-parameter-accept",
                        payload: "", from: connection.name}); 
                }
                break;

            case "file-transform-file-size-zero":
                var conn = users[data.name];
                if(conn != null) {
                    // setting that UserA connected with UserB 
                    sendTo(conn, {type: "file-transform-file-size-zero",
                        payload: "", from: connection.name}); 
                }
                break;

            case "save-data-over":
                var conn = users[data.name];
                if(conn != null) {
                    // setting that UserA connected with UserB 
                    sendTo(conn, {type: "save-data-over", payload: "", from: connection.name}); 
                }
                break;

            case "file-transform-cancel":
                var conn = users[data.name];
                if(conn != null) {
                    // setting that UserA connected with UserB 
                    sendTo(conn, {type: "file-transform-cancel", payload: "", from: connection.name}); 
                }
                break;

            case "offer-loopback": 
                // for ex. UserA wants to call UserB, but we need UserB to create offer
                console.log("Sending offer-loopback to: ", data.name);
                var conn = users[data.name]; 
                if(conn != null) {
                    sendTo(conn, {type: "offer-loopback", from: connection.name}); 
                }
                break;
                
            case "peer-excced-3":
                var conn = users[data.name];
                if(conn != null) {
                    // setting that UserA connected with UserB 
                    sendTo(conn, {type: "peer-excced-3", payload: "", from: connection.name}); 
                }
                break;

            case "offer": 
                // for ex. UserA wants to call UserB 
                console.log("Sending offer to: ", data.name);
                var conn = users[data.name]; 
                if(conn != null) {
                    //setting that UserA connected with UserB 
                    connection.otherName = data.name; 
                    sendTo(conn, {type: "offer", payload: data.payload, from: connection.name}); 
                }
                break;
                
            case "answer": 
                console.log("Sending answer to: ", data.name); 
                //for ex. UserB answers UserA 
                var conn = users[data.name]; 
                if(conn != null) {
                //setting that UserB connected with UserA 
                    connection.otherName = data.name; 
                    sendTo(conn, {type: "answer", payload: data.payload, from: connection.name}); 
                } 
                break; 
                
            case "candidate": 
                console.log("Sending candidate to:",data.name); 
                var conn = users[data.name];
                if(conn != null) {
                    sendTo(conn, {type: "candidate", payload: data.payload, from: connection.name}); 
                } 
                break;
                
            case "leave": 
                console.log("Send Disconnect message to: ", data.name); 
                var conn = users[data.name];
                if(conn){
                    conn.otherName = null; 
                    //notify the other user so he can disconnect his peer connection 
                    sendTo(conn, {type: "leave", from: connection.name}); 
                }
                break;

            default: 
                sendTo(connection, {type: "error", payload: "Command not found: " + data.type}); 
                break; 
        }
    }); 
    
    //when user exits, for example closes a browser window 
    //this may help if we are still in "offer","answer" or "candidate" state 
    connection.on("close", function() {
        if(connection.name) {
            delete users[connection.name]; 
            if(connection.otherName) {
                console.log("Disconnecting from ", connection.otherName); 
                var conn = users[connection.otherName]; 
                if(conn) {
                    conn.otherName = null;
                    sendTo(conn, {type: "leave", from: connection.name}); 
                }
            }
        }
    });

});

function sendTo(connection, message) {
    connection.send(JSON.stringify(message)); 
}
